//
//  LGAudioPlayer.m
//  下载地址：https://github.com/gang544043963/LGAudioKit
//
//  Created by ligang on 16/8/20.
//  Copyright © 2016年 LG. All rights reserved.
//

#import "AudioPlayer.h"
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#include "amrFileCodec.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import "lame.h"

#pragma clang diagnostic ignored "-Wdeprecated"

NSString *const kXMNAudioDataKey;

@interface AudioPlayer()<AVAudioPlayerDelegate>
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
@property (nonatomic, strong) NSOperationQueue *audioDataOperationQueue;
@property (nonatomic, assign) AudioPlayerState audioPlayerState;

@end

@implementation AudioPlayer

+ (void)initialize {
	//配置播放器配置
	[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
}

- (instancetype)init {
	self = [super init];
	if (self) {
		_audioDataOperationQueue = [[NSOperationQueue alloc] init];
		_index = NSUIntegerMax;
	}
	return self;
}

+ (instancetype)sharePlayer{
	static dispatch_once_t onceToken;
	static id shareInstance;
	dispatch_once(&onceToken, ^{
		shareInstance = [[self alloc] init];
	});
	return shareInstance;
}

#pragma mark - Public Methods

- (void)playAudioWithURLString:(NSString *)URLString atIndex:(NSUInteger)index{
	if (!URLString) {
		return;
	}
	//如果来自同一个URLString并且index相同,则直接取消
	if ([self.URLString isEqualToString:URLString] && self.index == index) {
		[self stopAudioPlayer];
		[self setAudioPlayerState:AudioPlayerStateCancel];
		return;
	}
	
	self.URLString = URLString;
	self.index = index;
	
	NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
        
		NSData *audioData = [self audioDataFromURLString:URLString atIndex:index];
		if (!audioData) {
			[self setAudioPlayerState:AudioPlayerStateCancel];
			return;
        }else{
            
        }
		dispatch_async(dispatch_get_main_queue(), ^{
			[self playAudioWithData:audioData];
		});
	}];
	[_audioDataOperationQueue addOperation:blockOperation];
}

- (void)stopAudioPlayer {
	if (_audioPlayer) {
		_audioPlayer.playing ? [_audioPlayer stop] : nil;
		_audioPlayer.delegate = nil;
		_audioPlayer = nil;
		[[AudioPlayer sharePlayer] setAudioPlayerState:AudioPlayerStateCancel];
		[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategorySoloAmbient error:nil];
		//恢复外部正在播放的音乐
		[[AVAudioSession sharedInstance] setActive:NO
										 withFlags:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
											 error:nil];
	}
}

- (void)playAudioOnlineWithContentsOfURL:(NSURL *)url{
    NSData * data = [[NSData alloc] initWithContentsOfURL:url];
    _audioPlayer = [[AVAudioPlayer alloc] initWithData:data error:nil];
    [_audioPlayer prepareToPlay];
    [_audioPlayer play];
}

#pragma mark - Private Methods
- (NSData *)audioDataFromURLString:(NSString *)URLString atIndex:(NSUInteger)index{
	NSData *audioData;

	if ([URLString hasSuffix:@".caf"] || [URLString hasSuffix:@".wav"] || [URLString hasSuffix:@".mp3"]) {//播放本机录制的文件
		audioData = [NSData dataWithContentsOfFile:URLString];
	} else if ([URLString hasSuffix:@".amr"]) {//播放安卓发来的AMR文件
		audioData = DecodeAMRToWAVE([NSData dataWithContentsOfFile:URLString]);
	} else {
        audioData = [NSData dataWithContentsOfFile:URLString];
		NSLog(@"soundFile not support!");
	}
	
	if (audioData) {
		objc_setAssociatedObject(audioData, &kXMNAudioDataKey, [NSString stringWithFormat:@"%@_%ld",URLString,index], OBJC_ASSOCIATION_COPY);
	}
	
	return audioData;
}

- (void)playAudioWithData:(NSData *)audioData {
	[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
	NSString *audioURLString = objc_getAssociatedObject(audioData, &kXMNAudioDataKey);
	if (![[NSString stringWithFormat:@"%@_%ld",self.URLString,self.index] isEqualToString:audioURLString]) {
		return;
	}
	
	NSError *audioPlayerError;
	_audioPlayer = [[AVAudioPlayer alloc] initWithData:audioData error:&audioPlayerError];
	if (!_audioPlayer || !audioData) {
		[self setAudioPlayerState:AudioPlayerStateCancel];
		return;
	}
	
	[[UIDevice currentDevice] setProximityMonitoringEnabled:YES];
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityStateChanged:) name:UIDeviceProximityStateDidChangeNotification object:nil];
	
	_audioPlayer.volume = 1.0f;
	_audioPlayer.delegate = self;
	[_audioPlayer prepareToPlay];
	[self setAudioPlayerState:AudioPlayerStatePlaying];
	[_audioPlayer play];
}

- (void)cancelOperation {
	for (NSOperation *operation in _audioDataOperationQueue.operations) {
		[operation cancel];
		break;
	}
}

- (void)proximityStateChanged:(NSNotification *)notification {
	if ([[UIDevice currentDevice] proximityState] == YES) {
		[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
	}else {
		[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
	}
}

#pragma mark - Setters

- (void)setURLString:(NSString *)URLString {
	if (_URLString) {
		//说明当前有正在播放,或者正在加载的视频,取消operation(如果没有在执行任务),停止播放
		[self cancelOperation];
		[self stopAudioPlayer];
		[self setAudioPlayerState:AudioPlayerStateCancel];
	}
	_URLString = [URLString copy];
}

- (void)setAudioPlayerState:(AudioPlayerState)audioPlayerState{
	_audioPlayerState = audioPlayerState;
	if (self.delegate && [self.delegate respondsToSelector:@selector(audioPlayerStateDidChanged:forIndex:)]) {
		[self.delegate audioPlayerStateDidChanged:_audioPlayerState forIndex:self.index];
	}
	if (_audioPlayerState == AudioPlayerStateCancel || _audioPlayerState == AudioPlayerStateNormal) {
		_URLString = nil;
//		_index = NSUIntegerMax;
	}
}

#pragma mark - AVAudioPlayerDelegate

- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
	[self setAudioPlayerState:AudioPlayerStateNormal];
	
	//删除近距离事件监听
	[[UIDevice currentDevice] setProximityMonitoringEnabled:NO];
	[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceProximityStateDidChangeNotification object:nil];
	
	//延迟一秒将audioPlayer 释放
	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .2f * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
		[self stopAudioPlayer];
	});
	
}

- (NSString *) audioPCMtoMP3:(NSString *)audioFileSavePath{
    NSLog(@"转码开始---");
    
    NSString *mp3FilePath = [self generateAudioFilePathWithDate:[NSDate date] andExt:@"mp3"];
    CFAbsoluteTime startTime =CFAbsoluteTimeGetCurrent();

    @try {
        int read, write;
        
        FILE *pcm = fopen([audioFileSavePath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([mp3FilePath cStringUsingEncoding:1], "wb");  //output 输出生成的Mp3文件位置
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        //设置声道1单声道，2双声道
        lame_set_num_channels(lame,1);
        lame_set_in_samplerate(lame, 8000.0);
        lame_set_VBR(lame, vbr_off);
        lame_init_params(lame);
        
        do {
            read = (int)fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame,pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    NSLog(@"转码结束----");
    CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
    
    NSLog(@"Linked in %f ms", linkTime *1000.0);
    return mp3FilePath;
    
}



- (NSString *)audio_PCMtoMP3WithFilePath:(NSString *)filePath {
    NSString *cafFilePath = filePath;    //caf文件路径
    NSString *mp3FileName = [self generateAudioFilePathWithDate:[NSDate date] andExt:@"mp3"];
    
    NSString *mp3FileName2 = [self generateAudioFilePathWithDate:[NSDate date] andExt:@"txt"];
    
    // 写入文件
    NSString *str = @"Hello, world!";
    NSString *fff = mp3FileName2;
    [str writeToFile:fff atomically:YES encoding:NSUTF8StringEncoding error:nil];

//    // 读取文件
//    NSString *content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
//    NSLog(@"%@", content);

    
    @try {
        int read, write;
        
        FILE *pcm = fopen([cafFilePath cStringUsingEncoding:1], "rb");  //source 被转换的音频文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
        FILE *mp3 = fopen([mp3FileName cStringUsingEncoding:1], "wb");  //output 输出生成的Mp3文件位置
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        lame_set_num_channels(lame, 2);//设置1为单通道，默认为2双通道
        lame_set_in_samplerate(lame, 11025.0);//11025.0        8000.0
        //        lame_set_VBR(lame, vbr_default);
        lame_set_brate(lame, 16);
        lame_set_mode(lame, 3);
        lame_set_quality(lame, 2);
        lame_init_params(lame);
        
        do {
            read = (int)fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
            write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
            write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
    }
    @catch (NSException *exception) {
        NSLog(@"%@",[exception description]);
    }
    @finally {

    }
    return mp3FileName;
}

//生成音频文件路径地址
- (NSString *)generateAudioFilePathWithDate:(NSDate *)date andExt:(NSString *)ext {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
       [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
       NSString *dateString = [formatter stringFromDate:date];
    NSString *dateStr = [NSString stringWithFormat:@"%ld", [self timeStampWithDate:dateString]];
//    NSString *directoryPath = [self getAudioDirectoryPath];
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
    NSString *directoryPath = [NSString stringWithFormat:@"%@/soundFile",cachePath];
    if (![[NSFileManager defaultManager] fileExistsAtPath:directoryPath]) {
        [[NSFileManager defaultManager] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    NSString *filePath = [NSString stringWithFormat:@"%@/%@.%@",directoryPath,dateStr,ext];
    return filePath;
}

//- (NSString *)getAudioDirectoryPath {
//    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject];
////    NSString *cachePath = NSHomeDirectory();
//    NSString *directoryPath = [NSString stringWithFormat:@"%@/soundFile",cachePath];
//    return directoryPath;
//}

- (long)timeStampWithDate:(NSString *)str {
    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *resDate = [formatter dateFromString:str];
    return [resDate timeIntervalSince1970] * 1000;
}

@end
